using System;
using System.Configuration;
using System.Diagnostics;
using System.Net;
using System.Security;
using System.Text.RegularExpressions;
using System.Web;
using System.Xml;
using CrmServiceWebReference;
using KalDev;
using Resources;

/// <summary>
/// Summary description for Common
/// </summary>
public sealed class Common
{
    private static readonly object syncRoot = new object();
    private static volatile Common instance;

    private Common()
    {
    }

    public static Common Instance
    {
        get
        {
            if (instance == null)
            {
                lock (syncRoot)
                {
                    if (instance == null)
                    {
                        instance = new Common();
                    }
                }
            }
            return instance;
        }
    }

    /// <summary>
    /// Removes the HTML tags.
    /// Removes comments
    /// Removes DOCTYPE's
    /// Configured from the resources files, so if there is any HTML tags that slips through you can add it in the resource file
    /// </summary>
    /// <param name="input">The input.</param>
    /// <returns></returns>
    public static string removeHTMLTags(string input)
    {
        return Regex.Replace(input, "<(.|\n)*?>", "");
    }

    public static int findOrderNumberInEmailBody(string emailBodyToParse)
    {
        int orderNumber;
        string orderNumberInString =
            Regex.Match(emailBodyToParse, Resources.Resource.RegularExpresionToExtractOrderNumber).ToString();
        int.TryParse(orderNumberInString, out orderNumber);
        return orderNumber;
    }

    /// <summary>
    /// Creates the Authorizations header for the KMS Search Service.
    /// This has been changed, and no longer require the password, but it does require
    /// the 
    /// </summary>
    /// <returns></returns>
    public static AuthHeader CreateAuthorizationHeader()
    {
        AuthHeader header = new AuthHeader();
        header.Username = ConfigurationManager.AppSettings["KalHeader.Username"];
        header.Password = ConfigurationManager.AppSettings["KalHeader.Password"];
        return header;
    }

    /// <summary>
    /// Creates the security and configuring the credentials for use with the KMS web services
    /// </summary>
    /// <remarks>
    /// Set a timeout value based on a setting in the resource file
    /// Sets UnsafeAuthenticatedConnectionSharing =true
    /// </remarks>
    /// <returns></returns>
    public static CRMService KmsAuthorize()
    {
        CRMService service = new CRMService();

        service.Credentials = Credential();

        service.AuthHeaderValue = CreateAuthorizationHeader();
        service.Timeout = int.Parse(Resource.WebServiceTimeOut);
        return service;
    }

    /// <summary>
    /// Write exceptions to the event logs
    /// </summary>
    public static void LogErrorMessage(Exception errorHandler)
    {
        // CreateInCrm the source, if it does not already exist.
        if (!EventLog.SourceExists("WrapperSearchService"))
        {
            //An event log source should not be created and immediately used.
            //There is a latency time to enable the source, it should be created
            //prior to executing the application that uses the source.
            //Execute this sample a second time to use the new source.
            EventLog.CreateEventSource("WrapperSearchService", "Application");
        }

        // CreateInCrm an EventLog instance and assign its source.
        EventLog myLog = new EventLog();
        myLog.Source = "WrapperSearchService";
        try
        {
            myLog.WriteEntry(errorHandler.InnerException.Data.ToString(), EventLogEntryType.Error);
        }
        catch (NullReferenceException)
        {
            myLog.WriteEntry(errorHandler.Message, EventLogEntryType.Warning);
        }
    }

    /// <summary>
    /// Creates the crm microsoftCrmWebService
    /// </summary>
    /// <returns></returns>
    public static CrmService CrmAutorize()
    {
        CrmService service = new WebServiceKeptAlive();

        service.Timeout = -1;
        service.Credentials = Credential();
        return service;
    }

    /// <summary>
    /// Creates credentials based on settings in the web.config
    /// if UseIntegratedAuthentication is set to false, it use the configured KalDevUserName,KalDevPassword,KalDevDomain
    /// else it use integrated authentication
    /// </summary>
    /// <returns></returns>
    public static NetworkCredential Credential()
    {
        NetworkCredential credential;

        if (ConfigurationManager.AppSettings[Resource.AppSettingsUseIntegratedAuthentication].ToLower().Contains("true"))
        {
            credential = (NetworkCredential) CredentialCache.DefaultNetworkCredentials;
        }
        else
        {
            string userName = ConfigurationManager.AppSettings[Resource.AppSettingsKalDevUserName];
            string password = ConfigurationManager.AppSettings[Resource.AppSettingsKalDevPassword];
            string domain = ConfigurationManager.AppSettings[Resource.AppSettingsKalDevDomain];

            credential = new NetworkCredential(userName, password, domain);
        }

        return credential;
    }

    /// <summary>
    /// Returns the users work in progress queue, based on credentials
    /// </summary>
    /// <returns></returns>
    public static queue wipQueue()
    {
        WhoAmIRequest userRequest = new WhoAmIRequest();
        WhoAmIResponse respons = new WhoAmIResponse();
        WhoAmIResponse user = (WhoAmIResponse) CrmAutorize().Execute(userRequest);

        QueryByAttribute query = new QueryByAttribute();
        query.ColumnSet = new AllColumns();
        query.EntityName = EntityName.queue.ToString();
        query.Attributes = new string[] {"primaryuserid", "queuetypecode"};
        query.Values = new string[] {user.UserId.ToString(), "3"};
        BusinessEntityCollection results = CrmAutorize().RetrieveMultiple(query);
        return (queue) results.BusinessEntities[0];
    }

    /// <summary>
    /// Updates the config file.
    /// Roger requested that I subtract a hour of the date time and store that in the config file
    /// </summary>
    /// <param name="dateTime">The date time.</param>
    public static void updateConfigFile(string dateTime)
    {
        try
        {
            string configurationFile = configurationFilePath();
            XmlDocument xmldoc = new XmlDocument();
            if (configurationFile == null)
            {
                throw new ConfigurationErrorsException("Cant find configuration file");
            }

            xmldoc.Load(configurationFile);
            XmlNode node = xmldoc.DocumentElement.SelectSingleNode("//appSettings//add[@key='lastFeedbackRunDate']");

            if (!string.IsNullOrEmpty(node.Attributes[1].Value))
            {
                node.Attributes[1].Value = dateTime;
                xmldoc.Save(configurationFile);
            }
            //
            DateTime updateTime = DateTime.Parse(dateTime) - TimeSpan.FromHours(1);

            //update the cached setting
            ConfigurationManager.AppSettings.Set("lastFeedbackRunDate", updateTime.ToLongDateString());
        }
        catch (SecurityException error)
        {
            LogErrorMessage(error);
            throw;
        }
    }

    public static void updateConfigFile(int feedbackId)
    {
        try
        {
            string configurationFile = configurationFilePath();
            XmlDocument xmldoc = new XmlDocument();
            if (configurationFile == null)
            {
                throw new ConfigurationErrorsException("Cant find configuration file");
            }

            xmldoc.Load(configurationFile);
            XmlNode node = xmldoc.DocumentElement.SelectSingleNode("//appSettings//add[@key='lastImportedWebCase']");

            if (!string.IsNullOrEmpty(node.Attributes[1].Value))
            {
                node.Attributes[1].Value = feedbackId.ToString();
                xmldoc.Save(configurationFile);
            }
            //

            //update the cached setting
            ConfigurationManager.AppSettings.Set("lastImportedWebCase", feedbackId.ToString());
        }
        catch (SecurityException error)
        {
            LogErrorMessage(error);
            throw;
        }
    }

    public static void updateConfigFile(string key, string value)
    {
        string configurationFile = configurationFilePath();
        XmlDocument xmldoc = new XmlDocument();
        if (configurationFile == null)
        {
            throw new ConfigurationErrorsException("Cant find configuration file");
        }

        xmldoc.Load(configurationFile);
        XmlNode node = xmldoc.DocumentElement.SelectSingleNode("//appSettings//add[@key='" + key + "']");

        if (!string.IsNullOrEmpty(node.Attributes[1].Value))
        {
            node.Attributes[1].Value = value;
            xmldoc.Save(configurationFile);
        }
        //update the cached setting
        ConfigurationManager.AppSettings.Set(key, value);
    }

    private static string configurationFilePath()
    {
        string configFileLocation =
            string.Concat(HttpContext.Current.Request.PhysicalApplicationPath, Resource.ConfigurationFile);
        return configFileLocation;
    }
}